10 //////////////////////
12 typedef int KeyType
; // type of key
14 typedef struct { // value related to key
18 // how to compare keys
19 #define compLT(a,b) (a < b)
20 #define compEQ(a,b) (a == b)
22 /////////////////////////////////////
23 // implementation independent code //
24 /////////////////////////////////////
28 RBT_STATUS_MEM_EXHAUSTED
,
29 RBT_STATUS_DUPLICATE_KEY
,
30 RBT_STATUS_KEY_NOT_FOUND
33 typedef enum { BLACK
, RED
} nodeColor
;
35 typedef struct NodeTag
{
36 struct NodeTag
*left
; // left child
37 struct NodeTag
*right
; // right child
38 struct NodeTag
*parent
; // parent
39 nodeColor color
; // node color (BLACK, RED)
40 KeyType key
; // key used for searching
41 ValType val
; // data related to key
44 #define SENTINEL &sentinel // all leafs are sentinels
45 static NodeType sentinel
= { SENTINEL
, SENTINEL
, 0, BLACK
, 0};
47 static NodeType
*root
= SENTINEL
; // root of red-black tree
49 static void rotateLeft(NodeType
*x
) {
51 // rotate node x to left
53 NodeType
*y
= x
->right
;
55 // establish x->right link
57 if (y
->left
!= SENTINEL
) y
->left
->parent
= x
;
59 // establish y->parent link
60 if (y
!= SENTINEL
) y
->parent
= x
->parent
;
62 if (x
== x
->parent
->left
)
72 if (x
!= SENTINEL
) x
->parent
= y
;
75 static void rotateRight(NodeType
*x
) {
77 // rotate node x to right
79 NodeType
*y
= x
->left
;
81 // establish x->left link
83 if (y
->right
!= SENTINEL
) y
->right
->parent
= x
;
85 // establish y->parent link
86 if (y
!= SENTINEL
) y
->parent
= x
->parent
;
88 if (x
== x
->parent
->right
)
98 if (x
!= SENTINEL
) x
->parent
= y
;
101 static void insertFixup(NodeType
*x
) {
103 // maintain red-black tree balance
104 // after inserting node x
106 // check red-black properties
107 while (x
!= root
&& x
->parent
->color
== RED
) {
108 // we have a violation
109 if (x
->parent
== x
->parent
->parent
->left
) {
110 NodeType
*y
= x
->parent
->parent
->right
;
111 if (y
->color
== RED
) {
114 x
->parent
->color
= BLACK
;
116 x
->parent
->parent
->color
= RED
;
117 x
= x
->parent
->parent
;
121 if (x
== x
->parent
->right
) {
122 // make x a left child
127 // recolor and rotate
128 x
->parent
->color
= BLACK
;
129 x
->parent
->parent
->color
= RED
;
130 rotateRight(x
->parent
->parent
);
134 // mirror image of above code
135 NodeType
*y
= x
->parent
->parent
->left
;
136 if (y
->color
== RED
) {
139 x
->parent
->color
= BLACK
;
141 x
->parent
->parent
->color
= RED
;
142 x
= x
->parent
->parent
;
146 if (x
== x
->parent
->left
) {
150 x
->parent
->color
= BLACK
;
151 x
->parent
->parent
->color
= RED
;
152 rotateLeft(x
->parent
->parent
);
159 // insert new node (no duplicates allowed)
160 RbtStatus
rbtInsert(KeyType key
, ValType val
) {
161 NodeType
*current
, *parent
, *x
;
163 // allocate node for data and insert in tree
165 // find future parent
168 while (current
!= SENTINEL
) {
169 if (compEQ(key
, current
->key
))
170 return RBT_STATUS_DUPLICATE_KEY
;
172 current
= compLT(key
, current
->key
) ?
173 current
->left
: current
->right
;
177 if ((x
= malloc (sizeof(*x
))) == 0)
178 return RBT_STATUS_MEM_EXHAUSTED
;
186 // insert node in tree
188 if(compLT(key
, parent
->key
))
198 return RBT_STATUS_OK
;
201 static void deleteFixup(NodeType
*x
) {
203 // maintain red-black tree balance
204 // after deleting node x
206 while (x
!= root
&& x
->color
== BLACK
) {
207 if (x
== x
->parent
->left
) {
208 NodeType
*w
= x
->parent
->right
;
209 if (w
->color
== RED
) {
211 x
->parent
->color
= RED
;
212 rotateLeft (x
->parent
);
213 w
= x
->parent
->right
;
215 if (w
->left
->color
== BLACK
&& w
->right
->color
== BLACK
) {
219 if (w
->right
->color
== BLACK
) {
220 w
->left
->color
= BLACK
;
223 w
= x
->parent
->right
;
225 w
->color
= x
->parent
->color
;
226 x
->parent
->color
= BLACK
;
227 w
->right
->color
= BLACK
;
228 rotateLeft (x
->parent
);
232 NodeType
*w
= x
->parent
->left
;
233 if (w
->color
== RED
) {
235 x
->parent
->color
= RED
;
236 rotateRight (x
->parent
);
239 if (w
->right
->color
== BLACK
&& w
->left
->color
== BLACK
) {
243 if (w
->left
->color
== BLACK
) {
244 w
->right
->color
= BLACK
;
249 w
->color
= x
->parent
->color
;
250 x
->parent
->color
= BLACK
;
251 w
->left
->color
= BLACK
;
252 rotateRight (x
->parent
);
261 RbtStatus
rbtErase(NodeType
* z
) {
264 if (z
->left
== SENTINEL
|| z
->right
== SENTINEL
) {
265 // y has a SENTINEL node as a child
268 // find tree successor with a SENTINEL node as a child
270 while (y
->left
!= SENTINEL
) y
= y
->left
;
273 // x is y's only child
274 if (y
->left
!= SENTINEL
)
279 // remove y from the parent chain
280 x
->parent
= y
->parent
;
282 if (y
== y
->parent
->left
)
285 y
->parent
->right
= x
;
295 if (y
->color
== BLACK
)
300 return RBT_STATUS_OK
;
304 NodeType
*rbtFind(KeyType key
) {
307 while(current
!= SENTINEL
) {
308 if(compEQ(key
, current
->key
)) {
311 current
= compLT (key
, current
->key
) ?
312 current
->left
: current
->right
;
318 // in-order walk of tree
319 void rbtInorder(NodeType
*p
, void (callback
)(NodeType
*)) {
320 if (p
== SENTINEL
) return;
321 rbtInorder(p
->left
, callback
);
323 rbtInorder(p
->right
, callback
);
326 // delete nodes depth-first
327 void rbtDelete(NodeType
*p
) {
328 if (p
== SENTINEL
) return;
334 void displayNode(NodeType
*p
) {
335 printf("%d %d\n", p
->key
, p
->val
.stuff
);
338 int main(int argc
, char **argv
) {
346 // process 2000 records
350 maxnum
= atoi(argv
[1]);
352 printf("maxnum = %d\n", maxnum
);
353 for (ct
= maxnum
; ct
; ct
--) {
354 key
= rand() % 90 + 1;
355 if ((p
= rbtFind(key
)) != NULL
) {
356 if (p
->val
.stuff
!= 10*key
) printf("fail val\n");
357 status
= rbtErase(p
);
358 if (status
) printf("fail: status = %d\n", status
);
362 status
= rbtInsert(key
, val
);
363 if (status
) printf("fail: status = %d\n", status
);
367 // output nodes in order
368 rbtInorder(root
, displayNode
);